'use client'; import { useState, useEffect } from 'react'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; interface SyncProgress { tableName: string; lastSyncDate: string; currentPage: number; totalProcessed: number; status: 'running' | 'completed' | 'error' | 'skipped'; lastError?: string; syncType: 'full' | 'delta' | 'rebuild'; startTime: number; endTime?: number; recordsSkipped?: number; } interface SyncConfig { pageSize: number; batchSize: number; maxWorkers: number; deltaSyncEnabled: boolean; cronSchedule: string; autoRefreshInterval: number; environment: string; } export default function NONSAPSyncPage() { const [syncProgress, setSyncProgress] = useState([]); const [isLoading, setIsLoading] = useState(false); const [lastUpdated, setLastUpdated] = useState(''); const [syncConfig, setSyncConfig] = useState(null); // 설정 정보 조회 const fetchSyncConfig = async () => { try { const response = await fetch('/api/nonsap-sync/config'); const result = await response.json(); if (result.success) { setSyncConfig(result.data); } else { console.error('Failed to fetch sync config:', result.error); } } catch (error) { console.error('Error fetching sync config:', error); } }; // 동기화 상태 조회 const fetchSyncStatus = async () => { try { const response = await fetch('/api/nonsap-sync/status'); const result = await response.json(); if (result.success) { setSyncProgress(result.data); setLastUpdated(result.timestamp); } else { console.error('Failed to fetch sync status:', result.error); } } catch (error) { console.error('Error fetching sync status:', error); } }; // 수동 동기화 트리거 const triggerSync = async () => { setIsLoading(true); try { const response = await fetch('/api/nonsap-sync/trigger', { method: 'POST' }); const result = await response.json(); if (result.success) { // 상태 새로고침 setTimeout(fetchSyncStatus, 2000); } else { alert('동기화 시작에 실패했습니다: ' + result.error); } } catch (error) { console.error('Error triggering sync:', error); alert('동기화 트리거 중 오류가 발생했습니다.'); } finally { setIsLoading(false); } }; // 상태별 배지 색상 const getStatusBadge = (status: string) => { switch (status) { case 'running': return 실행 중; case 'completed': return 완료; case 'error': return 오류; case 'skipped': return 완료됨; default: return 알 수 없음; } }; // Cron 스케줄을 사용자 친화적으로 변환 const formatCronSchedule = (cronSchedule: string) => { if (cronSchedule === '0 */30 * * * *') { return '30분마다'; } if (cronSchedule === '0 0 1 * * *') { return '매일 새벽 1시'; } return cronSchedule; // 기본값으로 원본 반환 }; // 동기화 타입별 배지 색상 const getSyncTypeBadge = (syncType: string) => { switch (syncType) { case 'delta': return 차분 동기화; case 'full': return 전체 동기화; case 'rebuild': return 삭제 후 재구성; default: return {syncType}; } }; // 초기 데이터 로드 useEffect(() => { fetchSyncConfig(); fetchSyncStatus(); }, []); // 자동 새로고침 useEffect(() => { if (!syncConfig) return; const interval = setInterval(fetchSyncStatus, syncConfig.autoRefreshInterval); return () => clearInterval(interval); }, [syncConfig]); return (

NONSAP 데이터 동기화

Oracle DB와 PostgreSQL 간의 데이터 동기화 상태를 모니터링합니다.

{lastUpdated && (

마지막 업데이트: {new Date(lastUpdated).toLocaleString('ko-KR')}

)}
{syncProgress.map((progress) => (
{progress.tableName}
{getSyncTypeBadge(progress.syncType)} {getStatusBadge(progress.status)}
마지막 동기화: {new Date(progress.lastSyncDate).toLocaleString('ko-KR')}
현재 페이지: {progress.currentPage}
처리된 레코드: {progress.totalProcessed.toLocaleString()}
{progress.recordsSkipped && progress.recordsSkipped > 0 && (
스킵된 레코드: {progress.recordsSkipped.toLocaleString()}
)} {progress.endTime && progress.startTime && (
실행 시간: {((progress.endTime - progress.startTime) / 1000).toFixed(2)}초
)} {progress.lastError && (

오류: {progress.lastError}

)}
))}
{syncProgress.length === 0 && (

동기화 정보가 없습니다. 동기화를 실행해보세요.

)} {syncConfig && ( 동기화 설정 테이블별 최적 동기화 방식을 자동 선택하여 실행됩니다. 멀티스레드로 병렬 처리하여 성능을 최적화합니다.

실행 환경: {syncConfig.environment}

동기화 방식: 테이블별 자동 선택 (차분/전체/재구성)

차분 동기화: {syncConfig.deltaSyncEnabled ? '활성화' : '비활성화'}

실행 주기: {formatCronSchedule(syncConfig.cronSchedule)}

페이지 크기: {syncConfig.pageSize.toLocaleString()}개 레코드

배치 크기: {syncConfig.batchSize.toLocaleString()}개 레코드

워커 수: {syncConfig.maxWorkers}개 (병렬 처리)

자동 새로고침: {(syncConfig.autoRefreshInterval / 1000)}초마다

동기화 대상: {syncProgress.length}개 테이블

)}
); }